import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import java.net.*;

public class TennisBallBlitz extends JApplet implements ActionListener, MouseListener, MouseMotionListener{
//Sounds =========================================================
	private AudioClip hitClip;
	private AudioClip bounceClip;
	private AudioClip pointsClip;
	private AudioClip crowdClip;
//Buttons ========================================================
	private JButton start_button;
	private JButton submit_button;
//Labels =========================================================
	private JLabel score_label;
	private JLabel gameover_label;
	private JLabel instructions;
	private JLabel focus_label;
	private JLabel signature;
	private JLabel court;
	private JLabel roger;
	private JLabel[] ball;
	private JLabel[] life;
	private JLabel points;
	private JLabel name_label;
//Text Field =====================================================
	private JFormattedTextField nameField1;
	private JTextField nameField;
//URLs ===========================================================
	private URL court_url = getClass().getResource("court.gif");
	private URL left_1_url = getClass().getResource("left1.gif");
	private URL left_2_url = getClass().getResource("left2.gif");
	private URL right_1_url = getClass().getResource("right1.gif");
	private URL right_2_url = getClass().getResource("right2.gif");
	private URL run_right_url = getClass().getResource("run_right.gif");
	private URL run_left_url = getClass().getResource("run_left.gif");
	private URL standing_url = getClass().getResource("standing.gif");
	private URL ball_big_url = getClass().getResource("ball_big.gif");
	private URL ball_med_url = getClass().getResource("ball_med.gif");
	private URL ball_sm_url = getClass().getResource("ball_sm.gif");
	private URL bonus_big_url = getClass().getResource("bonus_big.gif");
	private URL bonus_med_url = getClass().getResource("bonus_med.gif");
	private URL bonus_sm_url = getClass().getResource("bonus_sm.gif");
	private URL life_url = getClass().getResource("life.gif");
	private URL points_10_url = getClass().getResource("p10.gif");
	private URL points_25_url = getClass().getResource("p25.gif");
	private URL points_100_url = getClass().getResource("p100.gif");
	private URL instructions_url = getClass().getResource("instructions.png");
	private URL name_url = getClass().getResource("enter_name.png");
	private URL game_over_url = getClass().getResource("game_over.png");
//ImageIcons =====================================================
	private ImageIcon court_icon = new ImageIcon(court_url);
	private ImageIcon left_1_icon = new ImageIcon(left_1_url);
	private ImageIcon left_2_icon = new ImageIcon(left_2_url);
	private ImageIcon right_1_icon = new ImageIcon(right_1_url);
	private ImageIcon right_2_icon = new ImageIcon(right_2_url);
	private ImageIcon run_right_icon = new ImageIcon(run_right_url);
	private ImageIcon run_left_icon = new ImageIcon(run_left_url);
	private ImageIcon standing_icon = new ImageIcon(standing_url);
	private ImageIcon ball_big_icon = new ImageIcon(ball_big_url);
	private ImageIcon ball_med_icon = new ImageIcon(ball_med_url);
	private ImageIcon ball_sm_icon = new ImageIcon(ball_sm_url);
	private ImageIcon bonus_big_icon = new ImageIcon(bonus_big_url);
	private ImageIcon bonus_med_icon = new ImageIcon(bonus_med_url);
	private ImageIcon bonus_sm_icon = new ImageIcon(bonus_sm_url);
	private ImageIcon life_icon = new ImageIcon(life_url);
	private ImageIcon points_10_icon = new ImageIcon(points_10_url);
	private ImageIcon points_25_icon = new ImageIcon(points_25_url);
	private ImageIcon points_100_icon = new ImageIcon(points_100_url);
	private ImageIcon instructions_icon = new ImageIcon(instructions_url);
	private ImageIcon name_icon = new ImageIcon(name_url);
	private ImageIcon game_over_icon = new ImageIcon(game_over_url);
//Integers =======================================================	
	int score;					// this is the player's score
	int lives;					// the lives a player has left
	int theBall;				// which ball in the array
	int ballTimer;				// amount of time between balls
	int bonusCount;				// keeps track of consectutive inbounds points
	int[] bX = new int[9];		// the balls x coordinates
	int[] bY = new int[9];		// the balls y coordinates
	int[] bDX = new int[9];		// the ball's x direction
	int[] bDY = new int[9];		// the ball's y direction
	int[] bDT = new int[9];		// the ball's distance traveled
	int mX, mY;					// mouse coordinates
	int x, y;					// tennis player's coordinates
	int pX, pY;					// the points coordinates
	int swingCount;				// timing the swing
	int level;					// determines how frequently balls will generate
	int pCount;					// moves the points
//Boolean flag variables ==========================================
	Boolean gameOver;
	Boolean gameStarted;
	Boolean pointsOut;
	Boolean[] bonusBall = new Boolean[9];
	Boolean[] ballOut = new Boolean[9];
	
//Other Objects ===================================================
	Rectangle raquet = new Rectangle();
	Container pane = getContentPane();
	JPanel game;
	Timer gameTimer;
	String nameParam;
	String typeParam;
	String userName;
	
	public void init(){
		game = new JPanel();
		pane.add(game);
		game.setLayout(null);
		game.setBackground(new Color(198,74,8));
//load sound clips ========================================================================================
		hitClip = getAudioClip(getDocumentBase(),"hit_ball.wav");
		bounceClip = getAudioClip(getDocumentBase(),"bounce.wav");
		pointsClip = getAudioClip(getDocumentBase(),"points.wav");
		crowdClip = getAudioClip(getDocumentBase(),"crowd.mid");
//create and add the various buttons and labels that control the game =====================================
	//FOCUS LABEL
		focus_label = new JLabel("<html><span style='font-size: 12px; color: blue;'>CLICK TO START</span></html>");
		focus_label.setBounds(225, 350, 150, 40);
		game.add(focus_label);
		focus_label.setVisible(false);
	//NAME FIELD
		nameParam = getParameter("userName");
		typeParam = getParameter("userType");
		if(typeParam.equals("guest")){
			nameField = new JTextField(15);
			nameField.setEditable(true);
			nameField.setDocument(new JTextFieldLimit(10));
			nameField.setFont(new Font("verdana", Font.BOLD, 16));
			nameField.setBounds(220, 300, 160, 35);
			nameField.setText(nameParam);
			nameField.setVisible(false);
			game.add(nameField);
		}else{
			nameField = new JTextField(nameParam, 15);
			nameField.setEditable(false);
			userName = nameParam;
			nameField.setFont(new Font("verdana", Font.BOLD, 16));
			nameField.setBounds(220, 300, 160, 35);
			nameField.setVisible(false);
			game.add(nameField);
		}
	//NAME LABEL
		name_label = new JLabel(name_icon);
		name_label.setBounds(150,275,300,20);
		name_label.setVisible(false);
		game.add(name_label);
	//INSTRUCTIONS LABEL
		instructions = new JLabel(instructions_icon);
		instructions.setBounds(50, 50, 500, 300);
		game.add(instructions);	
	//START BUTTON
		start_button = new JButton("Start Game");
		start_button.setBounds(250, 350, 100, 40);
		start_button.addActionListener(this);
		game.add(start_button);
	//SUBMIT BUTTON
		submit_button = new JButton("Submit Score");
		submit_button.setBounds(225, 350, 150, 40);
		submit_button.addActionListener(this);
		game.add(submit_button);
		submit_button.setVisible(false);
	//SCORE LABEL
		score_label = new JLabel("<html><span style='color: white; font-size: 16px;'>Score "+score+"</span></html>");
		score_label.setBounds(450, 1, 150, 22);
		game.add(score_label);
	//SIGNATURE LABEL
		signature = new JLabel("<html><span style='font-size: 10px; color: blue;'>TheJavaArcade.com</span></html>");
		game.add(signature);
		signature.setBounds(420, 385, 180, 14);
	//GAMEOVER LABEL
		gameover_label = new JLabel(game_over_icon);
		gameover_label.setBounds(160, 80, 280, 25);
		game.add(gameover_label);
		gameover_label.setVisible(false);
	//LIFE LABELS
		life = new JLabel[10];
		for(int i=0; i<10; i++){
			life[i] = new JLabel(life_icon);
			game.add(life[i]);
		}
	//ROGER LABEL
		roger = new JLabel();
		game.add(roger);
	//BALL LABEL
		ball = new JLabel[9];
		for(int i=0; i<9; i++){
			ball[i] = new JLabel();
			ballOut[i] = false;
			game.add(ball[i]);
		}
	//POINTS LABEL
		points = new JLabel();
		game.add(points);
	//COURT LABEL
		court = new JLabel(court_icon);
		court.setBounds(81, 1, 438, 400);
		game.add(court);
//Add listeners and set the Timer =========================================================================
		addMouseListener(this);
		addMouseMotionListener(this);
		gameTimer = new Timer( 10, this);
		resetVars();
}
//MOUSELISTENERS ==========================================================================================
	public void mousePressed(MouseEvent e){
		if(gameStarted==true && swingCount==0){
			if(e.getButton()==MouseEvent.BUTTON1){swingCount =-60; raquet.setBounds(x,y+20,30, 20);}
			if(e.getButton()==MouseEvent.BUTTON3){swingCount = 60; raquet.setBounds(x+43,y+20,30, 20);}
		}
	}
	public void mouseReleased(MouseEvent e){}
	public void mouseClicked(MouseEvent e){}
//MOUSEMOTIONLISTENERS ====================================================================================
	public void mouseMoved(MouseEvent e){
		mX = e.getX();
		mY = e.getY();
	}
	public void mouseDragged(MouseEvent e){
		mX = e.getX();
		mY = e.getY();
	}
	public void mouseEntered(MouseEvent e){}
	public void mouseExited(MouseEvent e){}
//ACTIONLISTENERS =========================================================================================
	public void actionPerformed(ActionEvent evt) {
		if(evt.getSource()==start_button){
			instructions.setVisible(false);
			score_label.setText("<html><span style='color: white; font-size: 16px;'>Score "+score+"</span></html>");
			start_button.setVisible(false);
			gameTimer.start();
			gameStarted = true;
			game.requestFocus();
		}
//All events triggered by the gameTimer happen in here ==================================================
		if(evt.getSource()==gameTimer){
			if(gameStarted==true){
				if(swingCount==0){moveRoger();}
				if(swingCount!=0){swingRaquet();}
				ballTimer--;
				if(ballTimer==0){generateBall();}
				for(int i=0; i<9; i++){
					if(ballOut[i]==true){moveBall(i);}
				}
				if(pCount!=0){showPoints();}
			}
			//Stops the game when you run out of lives =================================================
			if(gameOver==true){
				gameTimer.stop();
				gameStarted = false;
				gameover_label.setVisible(true);
				submit_button.setVisible(true);
				nameField.setVisible(true);
				name_label.setVisible(true);
			}
			repaint();
			validate();		
		}
//The submittal of highscore via AJAX called here =======================================================
		if(evt.getSource() == submit_button){
			gameover_label.setVisible(false);
			submit_button.setVisible(false);
			requestFocus();
			repaint();
			nameField.setVisible(false);
			name_label.setVisible(false);
			userName = nameField.getText();
			userName = userName.replace("'","0");
			userName = userName.replace('"','0');
			try {getAppletContext().showDocument(new URL("javascript:insertScore('tennis','"+score+"','"+level+"','"+userName+"')"));}catch(MalformedURLException me) { }
			//RESET ALL VARIABLES
			instructions.setVisible(true);
			start_button.setVisible(true);
			repaint();
			requestFocus();
			resetVars();
		}

	}
// FUNCTIONS =======================================================================================
	public void resetVars(){
		gameStarted = false;
		gameOver = false;
		score = 0;
		level = 1;
		lives =10;
		ballTimer = 200;
		bonusCount = 0;
		theBall = 0;
		pCount = 0;
		x = 264;
		y = 335;
		swingCount = 0;
		roger.setIcon(standing_icon);
		setLives();
		points.setBounds(0,0,0,0);
		for(int i=0; i<9; i++){
			ball[i].setBounds(0,0,0,0);
			ballOut[i] = false;
			bonusBall[i] = false;
		}
	}
	//+++++++++++++++++++++++++++++++++++++++++++++++++MOVEROGER
	public void moveRoger(){
		if(mX > x+37){
			x = x + 2;
			roger.setIcon(run_right_icon);
			if(mX <= x+37){x = mX-37; roger.setIcon(standing_icon);}
		}
		if(mX < x+37){
			x = x - 2;
			roger.setIcon(run_left_icon);
			if(mX >= x+37){x = mX-37; roger.setIcon(standing_icon);}
		}
		roger.setBounds(x,y,73,62);
	}
	//++++++++++++++++++++++++++++++++++++++++++++++SWINGRAQUET
	public void swingRaquet(){
		if(swingCount < 0){
			if(swingCount<-40){roger.setIcon(left_1_icon);}
			if(swingCount>-41){roger.setIcon(left_2_icon);}
			swingCount++;
		}
		if(swingCount > 0){
			if(swingCount> 40){roger.setIcon(right_1_icon);}
			if(swingCount< 41){roger.setIcon(right_2_icon);}
			swingCount--;
		}
		if(swingCount==0){
			roger.setIcon(standing_icon);
			raquet.setBounds(0,0,0,0);
		}
	}
	//++++++++++++++++++++++++++++++++++++++++++++++GENERATEBALL
	public void generateBall(){
		double r1 = Math.random();
		if(level < 21){
			ballTimer = 300 - ((int)(r1 * 25)+(level * 4));
		}
		if(level > 19){
			ballTimer = 220 - ((int)(r1 * 25)+(level * 1));
		}
		double rDX = Math.random();
		bDX[theBall] = (int)(rDX *3)-1;
		bDY[theBall] = 2;
		double rX = Math.random();
		if(bDX[theBall]==-1){bX[theBall] = (int)(rX * 150) + 300;}
		if(bDX[theBall]== 0){bX[theBall] = (int)(rX * 300) + 150;}
		if(bDX[theBall]== 1){bX[theBall] = (int)(rX * 150) + 150;}
		bY[theBall] = -25;
		if(bonusCount>1){
			ball[theBall].setIcon(bonus_med_icon);
			bonusBall[theBall] = true;
			bonusCount = 0;
		}else{
			ball[theBall].setIcon(ball_med_icon);
			bonusBall[theBall] = false;
		}
		ballOut[theBall] = true;
		bDT[theBall] = 0;
		theBall++;
		if(theBall==9){theBall = 0;}
		level = level + 1;
	}
	//++++++++++++++++++++++++++++++++++++++++++++++MOVEBALL
	public void moveBall(int b){
		bDT[b]++;
		if(bDT[b]== 50 && bonusBall[b]==false){ball[b].setIcon(ball_big_icon);}
		if(bDT[b]== 50 && bonusBall[b]==true){ball[b].setIcon(bonus_big_icon);}
		if(bDT[b]==100 && bonusBall[b]==false){ball[b].setIcon(ball_med_icon);}
		if(bDT[b]==100 && bonusBall[b]==true){ball[b].setIcon(bonus_med_icon);}
		if(bDT[b]==109){
			if(bonusBall[b]==false){ball[b].setIcon(ball_sm_icon);}
			if(bonusBall[b]==true){ball[b].setIcon(bonus_sm_icon);}
			if(bDY[b]<0){
				pCount = 50;
				pY = bY[b];
				pX = bX[b];
				if(bX[b]+10 > (1/4.0)*bY[b] + 110 && bX[b] < 490-((1/4.0)*bY[b])){
					if(bonusBall[b]==true){
						crowdClip.play();
						pointsClip.play();
						points.setIcon(points_100_icon);
						score = score + 100;
					}else{
						pointsClip.play();
						points.setIcon(points_25_icon);
						score = score + 25;
						bonusCount++;
					}
				}else{
					bounceClip.play();
					points.setIcon(points_10_icon);
					score = score + 10;
					bonusCount = 0;
				}
				score_label.setText("<html><span style='color: white; font-size: 16px;'>Score "+score+"</span></html>");
			}
		}
		if(bDT[b]==118 && bonusBall[b]==false){ball[b].setIcon(ball_med_icon);}
		if(bDT[b]==118 && bonusBall[b]==true){ball[b].setIcon(bonus_med_icon);}
		bX[b] = bX[b] + bDX[b];
		bY[b] = bY[b] + bDY[b];
		int bH = ball[b].getIcon().getIconHeight();
		int bW = ball[b].getIcon().getIconWidth();
		ball[b].setBounds(bX[b], bY[b], bW, bH);
		if(ball[b].getBounds().intersects(raquet.getBounds())){
			hitClip.play();
			if(swingCount<41 && swingCount>26){bDX[b] = bDX[b]-2;}
			if(swingCount<27 && swingCount>13){bDX[b] = bDX[b]-1;}	
			if(swingCount>-41 && swingCount<-26){bDX[b] = bDX[b]+2;}
			if(swingCount>-27 && swingCount<-13){bDX[b] = bDX[b]+1;}
			bY[b] = y+6;
			bDY[b] = -2;
			bDT[b] = -8;
		}
		if(bY[b] > 425){
			bY[b]=0;
			ballOut[b] = false;
			lives = lives - 1;
			bonusCount = 0;
			setLives();
		}
	}
	public void setLives(){
		for(int i=0; i<10; i++){
			life[i].setBounds(0,0,0,0);
		}
		for(int i=0; i<lives; i++){
			life[i].setBounds((i*15)+15,5,10,10);
		}
		if(lives < 1){gameOver = true;}
	}
	public void showPoints(){
		pY--;
		points.setBounds(pX-8, pY, 42, 15);
		pCount--;
		if(pCount==0){points.setBounds(0,0,0,0);}
	}
}